package convert

import (
	"math"
	"strconv"
	"strings"
)

var n62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

func N62FormatUint(n uint64) string {
	var b []byte
	for {
		b = append(b, n62[n%62])
		n = n / 62
		if n == 0 {
			break
		}
	}
	ReverseBytes(b)
	return string(b)
}

func N62ParseUint(s string) (uint64, error) {
	if s == "" {
		return 0, strconv.ErrSyntax
	}
	if len(s) > 11 {
		return 0, strconv.ErrRange
	}
	if len(s) == 11 && strings.IndexByte(n62, s[0]) > strings.IndexByte(n62, 'l') { // MaxUint64 = lYGhA16ahyf
		return 0, strconv.ErrRange
	}
	b := []byte(s)
	ReverseBytes(b)
	var n uint64
	a := 1
	for _, c := range b {
		p := strings.IndexByte(n62, c)
		if p < 0 {
			return 0, strconv.ErrSyntax
		}
		n1 := n
		n += uint64(a * p)
		if n < n1 {
			return 0, strconv.ErrRange
		}
		a *= 62
	}
	return n, nil
}

func N62FormatInt(n int64) string {
	neg := false
	if n < 0 {
		neg = true
		n = -n
	}
	s := N62FormatUint(uint64(n))
	if neg {
		s = "-" + s
	}
	return s
}

func N62ParseInt(s string) (int64, error) {
	if s == "" {
		return 0, strconv.ErrSyntax
	}
	neg := false
	if s[0] == '-' {
		neg = true
		s = s[1:]
	}
	if len(s) > 11 {
		return 0, strconv.ErrRange
	}
	if len(s) == 11 && strings.IndexByte(n62, s[0]) > strings.IndexByte(n62, 'a') { // MaxInt64 = aZl8N0y58M7, MinInt64 = -aZl8N0y58M8
		return 0, strconv.ErrRange
	}
	u, err := N62ParseUint(s)
	if err != nil {
		return 0, err
	}
	if neg {
		if u > uint64(-math.MinInt64) {
			return 0, strconv.ErrRange
		}
		return -int64(u), nil
	} else {
		if u > uint64(math.MaxInt64) {
			return 0, strconv.ErrRange
		}
		return int64(u), nil
	}
}
